package cn.csc.framework.common.util.object;


import lombok.SneakyThrows;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.converter.BidirectionalConverter;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;
import ma.glasnost.orika.metadata.Type;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zts
 */
public class CopyObjectUtils {
	/**
	 * 获取默认字段工厂
	 */
	private static final MapperFactory MAPPER_FACTORY;

	/**
	 * 默认字段实例
	 */
	private static final MapperFacade MAPPER_FACADE;

	/**
	 * 默认字段实例集合
	 */
	private static final Map<String, MapperFacade> CACHE_MAPPER_FACADE_MAP;


	static {
		// mapNulls 表示 原对象中的null不会拷贝到目标对象
		MAPPER_FACTORY = new DefaultMapperFactory.Builder().mapNulls(false).build();
		//MAPPER_FACTORY.getConverterFactory().registerConverter(new DateToString());
		//MAPPER_FACTORY.getConverterFactory().registerConverter(new TimestampToString());
		MAPPER_FACADE = MAPPER_FACTORY.getMapperFacade();
		CACHE_MAPPER_FACADE_MAP = new ConcurrentHashMap<>();
	}

	/**
	 * 映射实体（默认字段）
	 *
	 * @param toClass 映射类对象
	 * @param data    数据（对象）
	 * @return 映射类对象
	 */
	public static <E, T> E copyAtoB(T data, Class<E> toClass) {
		return MAPPER_FACADE.map(data, toClass);
	}

	/**
	 * 映射实体（自定义配置）
	 *
	 * @param toClass   映射类对象
	 * @param data      数据（对象）
	 * @param configMap 自定义配置
	 * @return 映射类对象
	 */
	public static <E, T> E copyAtoB(T data, Class<E> toClass, Map<String, String> configMap) {
		MapperFacade mapperFacade = getMapperFacade(toClass, data.getClass(), configMap);
		return mapperFacade.map(data, toClass);
	}

	/**
	 * 映射集合（默认字段）
	 *
	 * @param toClass 映射类对象
	 * @param data    数据（集合）
	 * @return 映射类对象
	 */
	public static <E, T> List<E> copeAlistToBlist(Collection<T> data,Class<E> toClass) {
		return MAPPER_FACADE.mapAsList(data, toClass);
	}


	/**
	 * 映射集合（自定义配置）
	 *
	 * @param toClass   映射类
	 * @param data      数据（集合）
	 * @param configMap 自定义配置
	 * @return 映射类对象
	 */
	public static <E, T> List<E> copeAlistToBlist(Class<E> toClass, Collection<T> data, Map<String, String> configMap) {
		T t = data.stream().findFirst().orElseThrow(() -> new RuntimeException("映射集合，数据集合为空"));
		MapperFacade mapperFacade = getMapperFacade(toClass, t.getClass(), configMap);
		return mapperFacade.mapAsList(data, toClass);
	}

	/**
	 * 获取自定义映射
	 *
	 * @param toClass   映射类
	 * @param dataClass 数据映射类
	 * @param configMap 自定义配置
	 * @return 映射类对象
	 */
	private static <E, T> MapperFacade getMapperFacade(Class<E> toClass, Class<T> dataClass, Map<String, String> configMap) {
		String mapKey = dataClass.getCanonicalName() + "_" + toClass.getCanonicalName();
		MapperFacade mapperFacade = CACHE_MAPPER_FACADE_MAP.get(mapKey);
		if (Objects.isNull(mapperFacade)) {
			MapperFactory factory = new DefaultMapperFactory.Builder().build();
			ClassMapBuilder classMapBuilder = factory.classMap(dataClass, toClass);
			configMap.forEach(classMapBuilder::field);
			classMapBuilder.byDefault().register();
			mapperFacade = factory.getMapperFacade();
			CACHE_MAPPER_FACADE_MAP.put(mapKey, mapperFacade);
		}
		return mapperFacade;
	}



//	/**
//	 * Date 转为 yyyy-MM-dd HH:mm:ss 时间格式
//	 */
//	static class DateToString extends BidirectionalConverter<Date, String> {
//
//		@Override
//		public String convertTo(Date date, Type<String> type, MappingContext mappingContext) {
//			//可以转成你想要的格式 yyyy/MM/dd HH:mm:ss 等等
//			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//			return format.format(date);
//		}
//
//		@SneakyThrows
//		@Override
//		public Date convertFrom(String s, Type<Date> type, MappingContext mappingContext) {
//            /*SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            return format.parse(s);*/
//			return null;
//		}
//	}
//
//	/**
//	 * Timestamp 转为 yyyy-MM-dd HH:mm:ss 时间格式
//	 */
//	static class TimestampToString extends BidirectionalConverter<Timestamp, String> {
//
//		@Override
//		public String convertTo(Timestamp date, Type<String> type, MappingContext mappingContext) {
//			//可以转成你想要的格式 yyyy/MM/dd HH:mm:ss 等等
//			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//			return format.format(date);
//		}
//
//		@SneakyThrows
//		@Override
//		public Timestamp convertFrom(String s, Type<Timestamp> type, MappingContext mappingContext) {
//			return null;
//		}
//	}

}
